;;************************************************************************
;; qplotobj.lsp 
;; code for quantile, quantile-quantile and normal-probability plot objects 
;; copyright (c) 1993-97 by Forrest W. Young
;;************************************************************************

;;************************************************************************
;; quantile-plot-proto for quantile and normal-probability plots
;;************************************************************************

(defun quantile-plot (data &key (title "Quantile Plot") nice-range
                           variable-label variable-labels
                           (points t) point-labels (reg-line t) 
                           (legend1 (send current-object :name))  
                           (legend2 "Quantile Plot")
                           location size (go-away t) (show t))
"Args: (data &key reg-line (title Quantile Plot) nice-range (variable-label value) variable-labels (points nil) point-labels location size (go-away t) (show t))
DATA is a sequence or a list of sequences. Makes quantile plot of the sequence or first sequence. By default a line plot is produced without a menu. Points and a menu are added if POINTS is T. When REG-LINE is t a regression line is to be added to the plot.  Range and tick-marks for y are determined by get-nice-range unless NICE-RANGE (list of min, max, num tick marks) is specified. Remaining arguments are the same as for scatterplots. Function written by Forrest Young to replace original by Luke Tierney."
  (when (not variable-labels) (setf variable-labels variable-label))
  (send quantile-plot-proto :new data :title title :point-labels point-labels
        :variable-labels variable-labels
        :location location :size size
        :legend1 legend1 :legend2 legend2
        :show-points-and-menu points 
        :reg-line reg-line :nice-range nice-range
        :go-away go-away :show show))

(defun normal-probability-plot (data &key  (title "Normal Probability Plot") nice-range
                           variable-label variable-labels
                           (points t) point-labels (reg-line t)
                           (legend1 (send current-object :name))  
                           (legend2 "Normal Probability Plot")
                           location size (go-away t) (show t))
"Args: (data &key reg-line (title Normal Probability Plot) nice-range (variable-label value) variable-labels (points nil) point-labels location size (go-away t) (show t))
DATA is a sequence or a list of sequences. Makes normal probability plot of the sequence or first sequence. By default a line plot is produced without a menu. Points and a menu are added if POINTS is T. When REG-LINE is t a regression line is to be added to the plot.  Range and tick-marks for y are determined by get-nice-range unless NICE-RANGE (list of min, max, num tick marks) is specified. Remaining arguments are the same as for scatterplots. Function written by Forrest Young to replace original by Luke Tierney."
  (when (not variable-labels) (setf variable-labels variable-label))
  (send quantile-plot-proto :new data 
        :npplot t
        :title title :point-labels point-labels
        :variable-labels variable-labels
        :location location :size size
        :legend1 legend1 :legend2 legend2
        :show-points-and-menu points 
        :reg-line reg-line :nice-range nice-range
        :go-away go-away :show show))

(defun qplot (data &rest args)
"Alias for quantile-plot"
  (apply #'quantile-plot data args))

(defproto quantile-plot-proto 
  '(data data-lists variables variable-labels nq-switch legend1 legend2
         x reg-line show-points-and-menu points) () 
  scatterplot-proto)

(defmeth quantile-plot-proto :data (&optional (sequence nil set))
"Args: (&optional sequence)
Sets or returns the plot data for the y-axis."
  (if set (setf (slot-value 'data) sequence))
  (slot-value 'data))

(defmeth quantile-plot-proto :data-lists (&optional (list nil set))
"Args: (&optional sequence)
Sets or returns the lists of plot data for the y-axis."
  (if set (setf (slot-value 'data-lists) list))
  (slot-value 'data-lists))

(defmeth quantile-plot-proto :variables (&optional (list nil set))
"Args: (&optional sequence)
Sets or returns the lists of plot data for the y-axis."
  (if set (setf (slot-value 'variables) list))
  (slot-value 'variables))

(defmeth quantile-plot-proto :variable-labels (&optional (list nil set))
"Args: (&optional sequence)
Sets or returns the lists of plot data for the y-axis."
  (if set (setf (slot-value 'variable-labels) list))
  (slot-value 'variable-labels))

(defmeth quantile-plot-proto :x (&optional (list nil set))
"Args: (&optional list)
Sets or returns the plot data for the x-axis."
  (if set (setf (slot-value 'x) list))
  (slot-value 'x))

(defmeth quantile-plot-proto :reg-line (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether there is a regression line."
  (if set (setf (slot-value 'reg-line) logical))
  (slot-value 'reg-line))


(defmeth quantile-plot-proto :points (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether points or a line represents the plot."
  (unless (send self :has-slot 'points) (send self :add-slot 'points))
  (if set (setf (slot-value 'points) logical))
  (slot-value 'points))

(defmeth quantile-plot-proto :nq-switch (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t for normap-probablity or nil for quantile plot."
  (if set (setf (slot-value 'reg-line) logical))
  (slot-value 'reg-line))

(defmeth quantile-plot-proto :show-points-and-menu 
  (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether to show points and menu."
  (if set (setf (slot-value 'show-points-and-menu) logical))
  (slot-value 'show-points-and-menu))

(defmeth quantile-plot-proto :legend1 (&optional (string nil set))
  (if set (setf (slot-value 'legend1) string))
  (slot-value 'legend1))

(defmeth quantile-plot-proto :legend2 (&optional (string nil set))
  (if set (setf (slot-value 'legend2) string))
  (slot-value 'legend2))


(defmeth quantile-plot-proto :isnew 
  (data &key npplot title variable-labels point-labels reg-line 
        nice-range (show-points-and-menu t pandm?) location size go-away show
        legend1 legend2 (points t points?))
  (cond
    ((and points? pandm?)
     (error-message "cannot use both show-points-and-menu and points arguments"))
    (points? (setf show-points-and-menu points))
    (pandm?  (setf points show-points-and-menu)))
  (call-next-method 2 :title title :variable-labels variable-labels
                    :location location :size size :go-away go-away 
                    :show nil)
  (send self :legend1 legend1)
  (send self :legend2 legend2)
  (send self :use-color t)
  (send self :points points)
  (send self :show-points-and-menu show-points-and-menu)
  (send self :point-labels point-labels)
  (let ((variable-label variable-labels))
    (send self :show-points-and-menu show-points-and-menu)
    (cond 
      (show-points-and-menu
       (send self :make-two-plot-menus
                "NPQ-Plot"
                :hotspot-items '(help dash new-x new-y dash link dash
                                 print save copy)
                :popup-items   '(showing-labels mouse resize-brush dash
                                 erase-selection focus-on-selection 
                                 view-selection show-all dash
                                 symbol color dash selection slicer))
      ; (send self :new-menu "NPQ-Plot"
      ;       :items '(help dash new-x new-y dash
      ;   link showing-labels mouse resize-brush dash
      ;   erase-selection focus-on-selection view-selection show-all dash
      ;   symbol color dash selection slicer dash
      ;   print save copy))
       )
      (t
       (send self :make-two-plot-menus
                "NPQ-Plot"
                :hotspot-items '(help dash new-x new-y dash
                                 print save copy)
                :popup-items   '(no-items))
       ;(send self :new-menu "NPQ-Plot"
       ;      :items '(help dash new-x new-y dash
       ;               print save copy))
       ;(send self :add-mouse-mode 'no-action
       ;      :title "No Action"
       ;      :click :do-nothing
       ;      :cursor 'no-action)
       ;(send self :mouse-mode 'no-action)
       ;(defun do-nothing ())
       ))
    (when (sequencep (select data 0))
          (send self :data-lists data)
          (when (not variable-labels) (repeat "Values" (length data)))
          (send self :variables variable-labels)
          (setf variable-label (first variable-labels))
          (setf data (first data)))
    (send self :x-axis t t 5)
    (send self :nq-switch (not npplot))
    (send self :new-plot data 
          :variable-label variable-label
          :point-labels point-labels
          :reg-line reg-line
          :nice-range nice-range)
    (when show (send self :show-window))
    (send self :mouse-mode (if points 'brushing 'selecting))
    (send self :showing-labels points)
    self))


(defmeth quantile-plot-proto :new-plot 
  (data &key variable-label point-labels reg-line nice-range)
  (let* ((points (send self :points))
         (point-labels (send self :point-labels))
         (index (order data))
         (y (sort-data data))
         (x (sort-data (/ (1+ (rank y)) (1+ (length y)))))
         (nq (normal-quant x))
         (nx (length x))
         (nq-switch (send self :nq-switch))
         (ab nil)
         (a nil)
         (b nil))
    (send self :start-buffering)
    (send self :clear)
    (send self :data data)
    (if nq-switch
        (send self :x nq)
        (send self :x x))
    (let ((y-range nice-range))
      (when (not y-range)
            (setf y-range (get-nice-range (min data) (max data) 4)))
      (send self :range 1 (nth 0 y-range) (nth 1 y-range))
      (send self :y-axis t t (nth 2 y-range)))
    (cond 
      (nq-switch 
       (send self :variable-label 0 "Z-Score of Fraction of Data")
       (send self :legend2 "Normal Probability Plot")
       (send self :range 0 -3 3)
       (send self :x-axis t t 7)
       (when (> nx 1)
             (send self :add-lines nq y :color 'blue :width 1)
             (when (send self :points)
                   (send self :add-points 
                         (select nq (rank data)) 
                         (select y  (rank data)) 
                         :color 'blue :symbol 'disk))
             (when (and reg-line (> (length (remove-duplicates nq)) 1))
                   (setf ab (send (regression-model nq y :print nil)
                                  :coef-estimates))
                   (setf a (first ab))
                   (setf b (second ab))
                   (send self :add-lines 
                         (list (/ (- (min y) a) b) (/ (- (max y) a) b))
                         (list (min y) (max y)) :color 'red :width 2))))
      (t
       (send self :variable-label 0 "Fraction of Data")
       (send self :legend2 "Quantile Plot")
       (send self :range 0 0 1)
       (send self :x-axis t t 5)
       (when (> nx 1)
             (send self :add-lines x y :color 'blue :width 1)
             (when (send self :points)
                   (send self :add-points 
                         (select x (rank data))
                         (select y (rank data)) ;x y
                         :color 'blue :symbol 'disk)))))
    (when (and (> nx 1) (send self :point-labels))
          (send self :point-label 
                (iseq (length point-labels)) 
                point-labels))
    (when (not variable-label) (setf variable-label ""))
    (send self :variable-label 1 variable-label)
    (send self :redraw)
    (send self :buffer-to-screen)
    ))   

(defmeth quantile-plot-proto :new-var (axis) 
  (cond
    ((equal axis "Y")
     (let* ((result (send self :new-variable-dialog axis))
            )
       (when (> (length result) 0)
             (setf result (select result 0))
             (cond 
               ((not result) (error-message "You must select a variable"))
               (t
                (send self :show-new-var axis result))))))
    ((equal axis "X")
     (send self :nq-switch (not (send self :nq-switch)))
     (send self :new-plot (send self :data) 
          :variable-label (send self :variable-label 1)
          :point-labels 
           (if (> (send self :num-points) 0)
               (send self :point-label (iseq (send self :num-points)))
               nil)
          :reg-line (send self :reg-line)
           ))))

(defmeth quantile-plot-proto :show-new-var (axis variable)
"Used by new-y button"
  (send self :new-plot (send current-data :variable variable)
        :variable-label variable
        :reg-line t))

(defmeth quantile-plot-proto :make-show-variables-list ()
"Used by new-y button"
  (remove (send self :variable-label 1) 
          (send self :variable-labels) :test 'equal))

(defmeth quantile-plot-proto :redraw ()
  (call-next-method)
  (let* ((line1 (+ (second (send self :margin)) 
                   (send self :text-ascent) (send self :text-descent)))
         (line2 (+ line1
                   (send self :text-ascent) (send self :text-descent) 1)))
    (send self :draw-text (send self :legend1)
          (floor (/ (first (send self :size)) 2)) line1 1 0)
    (send self :draw-text (send self :legend2)
          (floor (/ (first (send self :size)) 2)) line2 1 0)
    ))

(defmeth quantile-plot-proto :plot-help (&key (flush t))
  (let ((overlay (first (send self :slot-value (quote overlays)))))
    (plot-help-window (strcat "Help for " (send self :title))  :flush flush)
    (cond 
      ((not (send self :nq-switch))
       (paste-plot-help  
        (format nil "The Quantile plot (Q-Plot) pictures a variable's distribution by plotting the value of a specific datum versus the fraction of the data that is smaller than the specific datum. The jagged line represents the variable's distribution.~2%"))
       (paste-plot-help  
        (format nil "The plot is used to help decide on the symmetry of a variable's distribution. Symmetry is not displayed in the usual sense. Rather, for a symmetric distribution, the points in the upper half of the plot will stretch out toward the upper right the same way the points in the bottom half stretch out toward the lower left.~2%"))
       (paste-plot-help  
        (format nil "There are several reasons why symmetry is important for data analysis: 1) The center of a distribution is unambiguous for a symmetric distribution. 2) Symmetric distributions are easier to understand (the upper part is like the lower part); and 3) Symmetric distributions are amenable to stronger statistical analysis than asymmetric distributions.~2%")))
      (t
       (paste-plot-help  
        (format nil "The Normal Probability Plot (NP-Plot) pictures a variable's distribution by plotting the value of a specific datum versus the Z-score that would be obtained for the datum under the assumption of normality. That is, the Q-plot's Fraction of Data (empirical probability) is converted, for the NP-plot, into Z-Scores having the stated probability.~2%"))
    (paste-plot-help  
     (format nil "In this plot, the jagged line represents the variable's distribution and the straight line represents a normal distribution. If the jagged line is roughly linear, so that it approximately follows the straight line, the variable has an approximately normal distribution.~2%"))
    (paste-plot-help  
     (format nil "Systematic departures from a straight line indicate non-normality. Such departures include large deviations, which indicate outliers; asymmetric departures at one end or the other, indicating skewness; and horizontal segments, plateaus or gaps, which indicate discrete data.~2%"))
       (paste-plot-help  
        (format nil "Normality is important because very many inferential statistical procedures assume that the data are normally distributed. The normal-probability plot gives us a visual approach to checking on this critical assumption.~2%"))
       ))
       (when (send overlay :new-y)
             (paste-plot-help  
              (format nil "When you click on the Y button at the top of the graph you will be presented with a list of variables to display. Clicking on a variable will change the plot to display that variable on the Y-axis. (If there are only two varibles, it toggles between them.)~2%")))
    (when (send overlay :new-x)
          (paste-plot-help  
           (format nil "Clicking on the X button at the top of the graph toggles the X-axis between \"Fraction of Data\", and \"Z-Score of Fraction of Data\". It also toggles the entire graph between a Quantile Plot and a Normal Probability Plot.")))
    (show-plot-help)
        ))

;;************************************************************************
;; quantile-quantile-plot-proto
;;************************************************************************

(defun quantile-quantile-plot 
  (xdata ydata &key reg-line (title "Quantile-Quantile Plot") 
         nice-x-range nice-y-range (points nil)
         (legend1 (send current-object :name))  
         (legend2 "Quantile-Quantile Plot")
         (variable-labels (list "Ordered X Values" "Ordered Y Values"))  
         point-labels location size (go-away t) (show t))
"Args (xdata ydata &key points (title Quantile-Quantile Plot) reg-line point-labels  variable-labels location size (go-away t) (show t))
XDATA and YDATA are sequences which do not have to be the same length. Makes a quantile-quantile plot of the two sequences.  By default a line plot is produced without a menu. Points and a menu are added if POINTS is T. When REG-LINE is t a regression line is to be added to the plot.  Range and tick-marks for x and y are determined by get-nice-range unless NICE-RANGE-X and NICE-RANGE-Y (lists of min, max, num tick marks) are specified. Remaining arguments are the same as for scatterplots. Function written by Forrest Young to replace original by Luke Tierney."
  (send quantile-quantile-plot-proto :new xdata ydata :reg-line reg-line 
        :nice-x-range nice-x-range :nice-y-range nice-y-range
        :title title :point-labels point-labels
        :legend1 legend1 :legend2 legend2
        :show-points-and-menu points
        :variable-labels variable-labels :location location 
        :size size :go-away go-away :show show))

(defun qqplot (xdata ydata &rest args)
  (apply #'quantile-quantile-plot xdata ydata args))

(defproto quantile-quantile-plot-proto 
  '(xdata ydata reg-line show-points-and-menu same-nobs legend1 legend2) 
  () scatterplot-proto)

(defmeth quantile-quantile-plot-proto :xdata (&optional (list nil set))
"Args: (&optional list)
Sets or returns the plot data for the x-axis."
  (if set (setf (slot-value 'xdata) list))
  (slot-value 'xdata))

(defmeth quantile-quantile-plot-proto :ydata (&optional (sequence nil set))
"Args: (&optional sequence)
Sets or returns the plot data for the y-axis."
  (if set (setf (slot-value 'ydata) sequence))
  (slot-value 'ydata))

(defmeth quantile-quantile-plot-proto :reg-line (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether there is a regression line."
  (if set (setf (slot-value 'reg-line) logical))
  (slot-value 'reg-line))

(defmeth quantile-quantile-plot-proto :same-nobs 
  (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether the two plotted variables have the same number of observations."
  (if set (setf (slot-value 'same-nobs) logical))
  (slot-value 'same-nobs))

(defmeth quantile-quantile-plot-proto :show-points-and-menu 
  (&optional (logical nil set))
"Args: (&optional list)
Sets or returns t or nil for whether to show points and menu."
  (if set (setf (slot-value 'show-points-and-menu) logical))
  (slot-value 'show-points-and-menu))

(defmeth quantile-quantile-plot-proto :legend1 (&optional (string nil set))
  (if set (setf (slot-value 'legend1) string))
  (slot-value 'legend1))

(defmeth quantile-quantile-plot-proto :legend2 (&optional (string nil set))
  (if set (setf (slot-value 'legend2) string))
  (slot-value 'legend2))

(defmeth quantile-quantile-plot-proto :isnew 
  (xdata ydata &key reg-line nice-x-range nice-y-range title variable-labels 
         show-points-and-menu point-labels location size go-away show
         legend1 legend2)
  (call-next-method 2 :title title 
                    :location location :size size :go-away go-away :show nil)
  (send self :use-color t)
  (send self :show-points-and-menu show-points-and-menu)
  (send self :legend1 legend1)
  (send self :legend2 legend2)
  (cond 
      (show-points-and-menu
       (send self :make-two-plot-menus
                "QQ-Plot"
                :hotspot-items '(help dash new-x new-y dash link dash
                                 print save copy)
                :popup-items   '(showing-labels mouse resize-brush dash
                                 erase-selection focus-on-selection 
                                 view-selection show-all dash
                                 symbol color dash selection slicer))
      ; (send self :new-menu "QQ-Plot"
      ;       :items '(help dash 
      ;                     new-x new-y dash 
      ;                     showing-labels mouse resize-brush dash
      ;                     print save copy))
       )
      (t
       (send self :make-two-plot-menus
                "QQ-Plot"
                :hotspot-items '(help dash new-x new-y dash
                                 print save copy)
                :popup-items   '(no-items))
       ;(send self :new-menu "NPQ-Plot"
       ;            :items '(help dash new-x new-y dash
       ;               print save copy))
       ;(send self :add-mouse-mode 'no-action
       ;      :title "No Action"
       ;      :click :do-nothing
       ;      :cursor 'no-action)
       ;(send self :mouse-mode 'no-action)
       ;(defun do-nothing ())
       ))
  (send self :new-plot xdata ydata
        :variable-labels variable-labels
        :point-labels point-labels
        :reg-line reg-line
        :nice-x-range nice-x-range
        :nice-y-range nice-y-range)
  (when show (send self :show-window))
  self)

(defmeth quantile-quantile-plot-proto :new-plot 
  (xdata ydata &key variable-labels point-labels reg-line 
         nice-x-range nice-y-range)
  (let* ((x-sort (if (= (length xdata) (length ydata))
                     (sort-data xdata)
                     (if (= (length ydata) 1)
                         (list (mean xdata))
                         (quantile xdata (rseq 0 1 (length ydata))))))
         (y-sort (if (= (length xdata) (length ydata))
                     (sort-data ydata)
                     (if (= (length ydata) 1)
                         ydata
                         (quantile ydata (rseq 0 1 (length ydata)))))))
    (if (= (length xdata) (length ydata))
        (send self :same-nobs t)
        (send self :same-nobs nil))
    (send self :start-buffering)
    (send self :clear)
    (send self :xdata x-sort)
    (send self :ydata y-sort)
    (let ((x-range nice-x-range)
          (y-range nice-y-range))
      (when (not x-range)
            (setf x-range (get-nice-range (min xdata) (max xdata) 4)))
      (send self :range 0 (nth 0 x-range) (nth 1 x-range))
      (send self :x-axis t t (nth 2 x-range))
      (when (not y-range)
            (setf y-range (get-nice-range (min ydata) (max ydata) 4)))
      (send self :range 1 (nth 0 y-range) (nth 1 y-range))
      (send self :y-axis t t (nth 2 y-range)))
    (when (or (= (length x-sort) 1) (send self :show-points-and-menu))
          (send self :add-points x-sort y-sort :color 'blue :symbol 'square))
    (when (> (length x-sort) 1) 
          (send self :add-lines x-sort y-sort :color 'blue :width 2))
    (when (and reg-line (> (length (remove-duplicates x-sort)) 1))
          (let* ((ab (send (regression-model x-sort y-sort :print nil) 
                           :coef-estimates))
                 (a (first ab))
                 (b (second ab)))
            (send self :add-lines 
                  (list (/ (- (min ydata) a) b) (/ (- (max ydata) a) b))
                  (list (min ydata) (max ydata)) :color 'red :width 2)
            (send self :add-lines 
                  (list (/ (- (min ydata) 0) 1) (/ (- (max ydata) 0) 1))
                  (list (min ydata) (max ydata)) :type 'dashed)
                 ;:color 'green :width 2 
            ))
    (when (not variable-labels) (setf variable-labels (list "" "")))
    (when (not (first  variable-labels)) (setf (first  variable-labels) ""))
    (when (not (second variable-labels)) (setf (second variable-labels) ""))
    (send self :variable-label 0 (first variable-labels))
    (send self :variable-label 1 (second variable-labels))
    (send self :redraw)
    (send self :buffer-to-screen)
    ))


(defmeth quantile-quantile-plot-proto :redraw ()
  (call-next-method)
  (let* ((line1 (+ (second (send self :margin)) 
                   (send self :text-ascent) (send self :text-descent)))
         (line2 (+ line1 1
                   (send self :text-ascent) (send self :text-descent))))
    (send self :draw-text (send self :legend1)
          (floor (/ (first (send self :size)) 2)) line1 1 0)
    (send self :draw-text (send self :legend2)
          (floor (/ (first (send self :size)) 2)) line2 1 0)
    ))

(defmeth quantile-quantile-plot-proto :plot-help (&key (flush t))
      (let ((overlay (first (send self :slot-value (quote overlays))))
            (same-nobs (send self :same-nobs))
            )
        (plot-help-window (strcat "Help for " (send self :title))
                           :flush flush)
        (paste-plot-help  
         (format nil "The Quantile-Quantile plot (QQ-Plot) is used to compare the distributions of two variables. In the QQ-plot, the quantiles of two variables are plotted against each other, forming the jagged blue line. This line represents the relationship between the two distributions. "))
        (paste-plot-help  
         (format nil "Since, for these data, the two variables ~a the same number of observations,the jagged blue line is " (if same-nobs "have" "do not have")))
        (paste-plot-help 
            (if same-nobs
             (format nil " simply a plot of one sorted variable against the other sorted variable.~2%")
             (format nil " formed by plotting the quantiles of the entire set of observations for the variable with fewer values versus an interpolation of the variable with more values that yields the same quantiles.~2%")))
        (paste-plot-help
         (format nil "The blue line on the QQ-Plot tells us whether the two variables have distributions that have the same shape. If the line is roughly straight, the two variables have roughly the same shape. This is important to know, since many analyses assume that the variables are \"identically\" distributed, which means they have the same shape. When two variables are normally distributed, for example, they have the same shape.~2%"))
        (paste-plot-help  
         (format nil "CENTER AND SPREAD:~%The straight dashed black line represents two identically distributed variables (this line does not appear when the centers of the two variables are very different). The straight red line represents two variables whose distributions are the same shape and which have measures of center and spread which are like those of the observed variables. Such distributions are geometrically \"similar\", since they have the same shape.~2%"))
(paste-plot-help  
         (format nil "When the dashed and red lines are parallel but not near each other, the measures of spread of the observed distributions are about the same, but the centers are different. The the two lines are near each other but not parallel, then the observed distributions have roughly the same centers, but different spreads.~2%"))
(paste-plot-help (format nil "The measures of center and spread that are compared in this plot are the mean and variance of the quantiles."))
(paste-plot-help  
         (format nil "If the jagged blue line is systematically different from a straight line the distributions of the two variables do not have the same shape, and are not geometrically similar. Outliers appear as large deviations from the straight line.~2%"))
        (paste-plot-help  
         (format nil "If the jagged blue line is roughly straight, the two variables have aproximately the same shaped distributions. If the blue line approximately follows the dashed line, then the two distributions are roughly identical. If it approximately follows the red line, but not the dashed line, the two distributions are \"similar\", but have different centers and spreads.~2%"))
        (when (send overlay :new-y)
              (paste-plot-help  
               (format nil "When you click on the X or Y buttons at the top of the graph you will be presented with a list of variables to display. Clicking on a variable will change the plot to display the variable on the X or Y axis.")))
        (show-plot-help)
        ))

(provide "qplotobj")